﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using Medianamik.Core;
using Medianamik.Core.Sugar;
using Medianamik.Core.Synchronization;
using Medianamik.Globalization;
using Telerik.Web.UI;

namespace Medianamik.UI.Controls
{
    [ParseChildren(true)]
    public class MedianamikParentLookupStandalone : WebControl, INamingContainer
    {
        private RadMultiPage _multiPage;
        private const string EditFormPlaceHolderPrefix = "phEdit_";
        private const string SubGridValidationSummary = "subgridvalidationsummary";
        private const string GridPlaceHolderPrefix = "phGrid_";
        private const string AddButtonPrefix = "add_";
        private const string SaveButtonPrefix = "save_";
        private const string CancelButtonPrefix = "cancel_";
        protected const string ActionColumnUniqueName = "SubActionColumn";
        private ValidationSummary _valSummary;
        public readonly RadGrid Grid = new RadGrid();

        public void ForceEnsureChildControls()
        {
            IsDataBound = true;
            EnsureChildControls();
        }

        public override void DataBind()
        {
            base.OnDataBinding(EventArgs.Empty);

            // Create the control hierarchy.  First, clear out the child controls
            Controls.Clear();
            ClearChildViewState();
            TrackViewState();

            // Create the control hierarchy
            CreateControlHierarchyForNonTemplated(true);

            // Mark the hierarchy as having been created
            ChildControlsCreated = true;
        }

        protected override void CreateChildControls()
        {
            Controls.Clear();
            CreateControlHierarchyForNonTemplated(!IsDataBound);
        }

        protected bool IsDataBound
        {
            get
            {
                return ((bool?)ViewState["IsDataBound"]).GetValueOrDefault();
            }
            set { ViewState["IsDataBound"] = value; }
        }

        //private RadPageView _currentRadPageView;
        ////protected RadPageView CurrentRadPageView
        ////{
        ////    get { return _currentRadPageView ?? (_currentRadPageView = GetCurrentRadPageView()); }
        ////}

        //private RadPageView GetCurrentRadPageView()
        //{
        //    var parent = Parent;

        //    while (parent != null)
        //    {
        //        if (parent is RadPageView)
        //            return parent as RadPageView;

        //        parent = parent.Parent;
        //    }

        //    return null;
        //}

        private void CreateControlHierarchyForNonTemplated(bool useDataSource)
        {
            if (useDataSource)
            {
                IsDataBound = true;

                var lookupPropertyIds = new Dictionary<string, string[]>();
                var medianamikControlTypes = new Dictionary<string, string[]>();

                var editPlaceHolder = new PlaceHolder { ID = EditFormPlaceHolderPrefix + TypeName }; //Placeholder pour le mode d edition
                Controls.Add(editPlaceHolder);
                editPlaceHolder.Visible = false;

                AddValidators(editPlaceHolder, SubGridValidationSummary);

                var gridPlaceHolder = new PlaceHolder { ID = GridPlaceHolderPrefix + TypeName }; //Placeholder pour le mode grille
                Controls.Add(gridPlaceHolder);
                gridPlaceHolder.Visible = true;

                var medianamikLookupProperties = BuildLookupEditForm(true, editPlaceHolder, TypeName);

                lookupPropertyIds[TypeName] = medianamikLookupProperties.PropertyIds;
                medianamikControlTypes[TypeName] = medianamikLookupProperties.MedianamikControlTypes;

                gridPlaceHolder.Controls.Add(new LiteralControl("<p>"));

                var addButton = new Button { ID = AddButtonPrefix + TypeName };
                gridPlaceHolder.Controls.Add(addButton);
                addButton.Text = String.IsNullOrEmpty(AddButtonText) ?
                    Translator.Translate("Medianamik_Global", "Add") : AddButtonText;
                addButton.CssClass = "Btn";
                addButton.Click += AddButtonClick;
                addButton.CausesValidation = false;

                gridPlaceHolder.Controls.Add(new LiteralControl("</p>"));

                gridPlaceHolder.Controls.Add(new LiteralControl("<br />"));

                var saveButton = new Button();
                saveButton.ID = SaveButtonPrefix + TypeName;
                editPlaceHolder.Controls.Add(saveButton);
                saveButton.Text = Translator.Translate("medianamik_global", "SaveButtonText");
                saveButton.CssClass = "Btn";
                saveButton.ValidationGroup = SubGridValidationSummary;
                saveButton.CausesValidation = true;

                saveButton.Click += SaveButtonClick;

                editPlaceHolder.Controls.Add(new LiteralControl("&nbsp;"));

                var cancelButton = new Button();
                cancelButton.ID = CancelButtonPrefix + TypeName;
                editPlaceHolder.Controls.Add(cancelButton);
                cancelButton.Text = Translator.Translate("medianamik_global", "Cancel");
                cancelButton.CausesValidation = false;
                cancelButton.CssClass = "Btn";
                cancelButton.Click += CancelButtonClick;

                //Setup de la grille
                Grid.MasterTableView.DataKeyNames = new[] { "Id" };
                Grid.ItemCommand += GridItemCommand;
                //Grid.DataSource = GetRecordsForGrid();
                Grid.NeedDataSource += SubgridNeedDataSource;
                Grid.EnableEmbeddedSkins = false;
                Grid.Skin = "Medianamik";
                Grid.Width = Unit.Percentage(100);

                if (Columns.Count() > 0)
                {
                    foreach (var column in Columns)
                    {
                        var customColumn = new GridTemplateColumn
                        {
                            HeaderText = column.HeaderText,
                            UniqueName = Guid.NewGuid().ToString("N"),
                            ItemTemplate = new SubGridColumnTemplate(column.Name),
                            SortExpression = column.Name
                        };

                        Grid.MasterTableView.Columns.Add(customColumn);
                    }
                }
                else
                {
                    var customColumn = new GridTemplateColumn
                    {
                        HeaderText = Translator.Translate("Medianamik_ContentManagement",
                            "ContentNameColumn"),
                        UniqueName = Guid.NewGuid().ToString("N"),
                        ItemTemplate = new SubGridColumnTemplate(NameProperty),
                        SortExpression = NameProperty
                    };

                    Grid.MasterTableView.Columns.Add(customColumn);
                }

                Grid.MasterTableView.AllowCustomSorting = true;

                if (AllowLinesReordering)
                {
                    Grid.SortCommand += subgrid_SortCommand;
                    Grid.ClientSettings.AllowRowsDragDrop = true;
                    Grid.ClientSettings.EnableRowHoverStyle = true;
                    Grid.ClientSettings.Selecting.AllowRowSelect = true;
                    Grid.RowDrop += RowDrop;
                    Grid.ClientSettings.Selecting.EnableDragToSelectRows = true;
                    Grid.Columns[0].ItemStyle.CssClass = "DragCursor";
                }

                Grid.AllowSorting = AllowOrderByColumn;
                Grid.AllowPaging = false;
                Grid.AutoGenerateColumns = false;


                var actionColumn = new GridTemplateColumn
                {
                    HeaderText = "Actions",
                    UniqueName = ActionColumnUniqueName,
                    ItemTemplate = new SubGridActionColumnTemplate(OnEditSubItem,
                        OnDeleteSubItem)
                };

                Grid.MasterTableView.Columns.Add(actionColumn);

                actionColumn.ItemStyle.CssClass = "Actions";
                actionColumn.HeaderStyle.HorizontalAlign = HorizontalAlign.Center;
                actionColumn.HeaderStyle.Width = Unit.Percentage(1);
                Grid.MasterTableView.EnableColumnsViewState = false;

                Grid.ID = TypeName;
                gridPlaceHolder.Controls.Add(Grid);
                Grid.DataBind();

                SetLookupViewstate(lookupPropertyIds, medianamikControlTypes);
            }
            else
            {
                var editPlaceHolder = new PlaceHolder(); //Placeholder pour le mode d edition
                editPlaceHolder.ID = EditFormPlaceHolderPrefix + TypeName;
                var gridPlaceHolder = new PlaceHolder(); //Placeholder pour le mode grille
                gridPlaceHolder.ID = GridPlaceHolderPrefix + TypeName;

                Controls.Add(editPlaceHolder);

                AddValidators(editPlaceHolder, SubGridValidationSummary);

                Controls.Add(gridPlaceHolder);

                BuildLookupEditForm(false, editPlaceHolder, TypeName);

                gridPlaceHolder.Controls.Add(new LiteralControl("<p>"));

                var addButton = new Button { ID = AddButtonPrefix + TypeName };
                gridPlaceHolder.Controls.Add(addButton);
                addButton.Text = String.IsNullOrEmpty(AddButtonText) ?
                    Translator.Translate("Medianamik_Global", "Add") : AddButtonText;
                addButton.CssClass = "Btn";
                addButton.Click += AddButtonClick;
                addButton.CausesValidation = false;

                gridPlaceHolder.Controls.Add(new LiteralControl("</p>"));

                gridPlaceHolder.Controls.Add(new LiteralControl("<br />"));

                var saveButton = new Button { ID = SaveButtonPrefix + TypeName };
                editPlaceHolder.Controls.Add(saveButton);
                saveButton.Text = Translator.Translate("medianamik_global", "SaveButtonText");
                saveButton.CssClass = "Btn";
                saveButton.ValidationGroup = SubGridValidationSummary;
                saveButton.CausesValidation = true;

                saveButton.Click += SaveButtonClick;

                editPlaceHolder.Controls.Add(new LiteralControl("&nbsp;"));

                var cancelButton = new Button { ID = CancelButtonPrefix + TypeName };
                editPlaceHolder.Controls.Add(cancelButton);
                cancelButton.Text = Translator.Translate("medianamik_global", "Cancel");
                cancelButton.CausesValidation = false;
                cancelButton.CssClass = "Btn";
                cancelButton.Click += CancelButtonClick;



                //Setup de la grille
                Grid.MasterTableView.DataKeyNames = new[] { "Id" };
                Grid.ItemCommand += GridItemCommand;
                //Grid.DataSource = GetRecordsForGrid(Grid.MasterTableView.SortExpressions.GetSortString());
                Grid.NeedDataSource += SubgridNeedDataSource;
                Grid.EnableEmbeddedSkins = false;
                Grid.Skin = "Medianamik";
                Grid.Width = Unit.Percentage(100);

                if (Columns.Count() > 0)
                {
                    foreach (var column in Columns)
                    {
                        var customColumn = new GridTemplateColumn
                        {
                            HeaderText = column.HeaderText,
                            UniqueName = Guid.NewGuid().ToString("N"),
                            ItemTemplate = new SubGridColumnTemplate(column.Name),
                            SortExpression = column.Name
                        };

                        Grid.MasterTableView.Columns.Add(customColumn);
                    }
                }
                else
                {
                    var customColumn = new GridTemplateColumn
                    {
                        HeaderText = Translator.Translate("Medianamik_ContentManagement",
                        "ContentNameColumn"),
                        UniqueName = Guid.NewGuid().ToString("N"),
                        ItemTemplate = new SubGridColumnTemplate("Name"),
                        SortExpression = "Name"
                    };

                    Grid.MasterTableView.Columns.Add(customColumn);
                }
                Grid.MasterTableView.AllowCustomSorting = true;
                if (AllowLinesReordering)
                {
                    Grid.SortCommand += subgrid_SortCommand;
                    Grid.ClientSettings.AllowRowsDragDrop = true;
                    Grid.ClientSettings.EnableRowHoverStyle = true;
                    Grid.ClientSettings.Selecting.AllowRowSelect = true;
                    Grid.RowDrop += RowDrop;
                    Grid.ClientSettings.Selecting.EnableDragToSelectRows = true;
                    Grid.Columns[0].ItemStyle.CssClass = "DragCursor";
                }

                Grid.AllowSorting = AllowOrderByColumn;
                Grid.AllowPaging = false;
                Grid.AutoGenerateColumns = false;

                var actionColumn = new GridTemplateColumn
                {
                    HeaderText = "Actions",
                    UniqueName = ActionColumnUniqueName,
                    ItemTemplate = new SubGridActionColumnTemplate(OnEditSubItem,
                        OnDeleteSubItem)
                };

                Grid.MasterTableView.Columns.Add(actionColumn);

                actionColumn.ItemStyle.CssClass = "Actions";
                actionColumn.HeaderStyle.HorizontalAlign = HorizontalAlign.Center;
                actionColumn.HeaderStyle.Width = Unit.Percentage(1);
                Grid.MasterTableView.EnableColumnsViewState = false;

                Grid.ID = TypeName;
                gridPlaceHolder.Controls.Add(Grid);
            }

            if (!EnableClientScriptValidation)
            {
                _valSummary.EnableClientScript = false;
            }
        }

        void AddButtonClick(object sender, EventArgs e)
        {
            //Il faudrait peut-etre vider les controles d editions pour etre sur de n avoir aucune valeur a l ajout
            var lookupName = ((Button)sender).ID.Replace(AddButtonPrefix, "");
            var editForm = GetPlaceHolder(lookupName, EditFormPlaceHolderPrefix);
            var lookupIds = LookupPropertyIds[lookupName];

            foreach (var lookupControlId in lookupIds)
            {
                var control = ((BaseMedianamikControl)editForm.FindControl(lookupControlId));

                if (control.TypeOfValue.IsGenericType && control.TypeOfValue.GetGenericTypeDefinition() == typeof(Nullable<>))
                    ((BaseMedianamikControl)editForm.FindControl(lookupControlId)).SetValue(null);
                else
                    ((BaseMedianamikControl)editForm.FindControl(lookupControlId)).SetValue("");
            }

            var saveButton = (Button)editForm.FindControl(SaveButtonPrefix + lookupName);
            saveButton.CommandArgument = Guid.NewGuid().ToString();

            SwitchMode(lookupName, false);
        }

        public CultureInfo EditionCulture
        {
            get
            {
                var result = ViewState["EditionCulture"] as CultureInfo;

                if (result == null)
                    throw new Exception("MedianamikFormTemplate's EditionCulture property is mandatory.");

                return result;
            }
            set { ViewState["EditionCulture"] = value; }
        }

        public bool HideNeutralLanguageIndication
        {
            get
            {
                object o = ViewState["HideNeutralLanguageIndication"];
                if (o == null)
                    return default(bool);
                return (bool)o;
            }
            set { ViewState["HideNeutralLanguageIndication"] = value; }
        }

        public string NameProperty
        {
            get
            {
                return ViewState["NameProperty"] == null ? "name" :
                    ViewState["NameProperty"].ToString();
            }
            set { ViewState["NameProperty"] = value; }
        }

        public string MedianamikFormTemplateId
        {
            get
            {
                return ViewState["MedianamikFormTemplateId2"] == null ? null :
                    ViewState["MedianamikFormTemplateId2"].ToString();
            }
            set { ViewState["MedianamikFormTemplateId2"] = value; }
        }

        private MedianamikFormTemplate _medianamikFormTemplate;
        protected MedianamikFormTemplate MedianamikFormTemplate
        {
            get
            {
                return _medianamikFormTemplate ?? (_medianamikFormTemplate =
                   Page.FindControlsR<MedianamikFormTemplate>().FirstOrDefault(c =>
                    c.ID.EqualsIgnoreCase(MedianamikFormTemplateId)));
            }
        }

        public string TypeName
        {
            get
            {
                return ViewState["TypeName"] == null ? null :
                    ViewState["TypeName"].ToString();
            }
            set { ViewState["TypeName"] = value; }
        }

        public virtual string LookupPropertyName
        {
            get
            {
                return ViewState["LookupPropertyName"] == null ? null :
                    ViewState["LookupPropertyName"].ToString();
            }
            set { ViewState["LookupPropertyName"] = value; }
        }

        public virtual Guid? LookupId
        {
            get
            {
                return (Guid?)ViewState["LookupId"] == null ? null :
                    (Guid?)ViewState["LookupId"];
            }
            set { ViewState["LookupId"] = value; }
        }

        [Browsable(false)]
        public Record[] DataSource
        {
            get
            {
                return (ViewState["DataSource2"] == null ? new Record[] { } :
                    ViewState["DataSource2"] as Record[]);
            }
            set { ViewState["DataSource2"] = value; }
        }

        private PlaceHolder GetPlaceHolder(string lookupName, string placeholderPrefix)
        {
            return (PlaceHolder)Page.FindControlR(placeholderPrefix + lookupName);
        }

        public void SwitchMode(string lookupName, bool showGrid)
        {
            var editPlaceholder = GetPlaceHolder(lookupName, EditFormPlaceHolderPrefix);
            var gridPlaceholder = GetPlaceHolder(lookupName, GridPlaceHolderPrefix);

            if (showGrid)
            {
                gridPlaceholder.Visible = true;
                editPlaceholder.Visible = false;
            }
            else
            {
                gridPlaceholder.Visible = false;
                editPlaceholder.Visible = true;
            }
        }

        void CancelButtonClick(object sender, EventArgs e)
        {
            string lookupName = ((Button)sender).ID.Replace(CancelButtonPrefix, "");
            SwitchMode(lookupName, true);
        }

        void SaveButtonClick(object sender, EventArgs e)
        {
            Page.Validate(SubGridValidationSummary);

            if (Page.IsValid)
            {
                var lookupName = ((Button)sender).ID.Replace(SaveButtonPrefix, "");
                var editForm = GetPlaceHolder(lookupName, EditFormPlaceHolderPrefix);
                var lookupIds = LookupPropertyIds[lookupName];
                var recordId = new Guid(((Button)sender).CommandArgument);
                var gridSource = DataSource.ToList();
                var currentRecord = gridSource.FirstOrDefault(r => r.Id == recordId);

                var date = DateTime.Now;
                var user = MedianamikContext.Current.MedianamikUser.UserName;

                if (currentRecord == null)
                {
                    var newRecord = new Record
                    {
                        NodeTypeName = lookupName,
                        DefaultCultureName = EditionCulture.Name,
                        Id = recordId,
                        Position = short.Parse(gridSource.Count.ToString()),
                        CreatedOn = date,
                        CreatedBy = user,
                        UpdatedOn = date,
                        UpdatedBy = user,
                        ExistsInCurrentCulture = true
                    };

                    foreach (var lookupControlId in lookupIds)
                    {
                        var propertyName = lookupControlId.Replace(lookupName + "_", "");
                        var value = ((BaseMedianamikControl)editForm.FindControl(lookupControlId))
                            .GetValue();
                        var property = new RecordProperty
                        {
                            CultureName = EditionCulture.Name,
                            NodeTypePropertyName = propertyName,
                            Value = value
                        };
                        newRecord.Properties.Add(property);
                    }


                    if(LookupId.HasValue && !string.IsNullOrEmpty(LookupPropertyName))
                    {
                        newRecord.ParentId = LookupId;
                    }
                    else if (LookupPropertyName.ToLower().Equals("parentid"))
                    {
                        newRecord.ParentId = MedianamikFormTemplate.NodeId;
                    }
                    else
                    {
                        var lookupProperty = new RecordProperty
                        {
                            CultureName = EditionCulture.Name,
                            NodeTypePropertyName = LookupPropertyName,
                            Value = MedianamikFormTemplate.NodeId
                        };

                        newRecord.Properties.Add(lookupProperty);
                    }

                    gridSource.Add(newRecord);
                }
                else
                {
                    currentRecord.UpdatedOn = date;
                    currentRecord.UpdatedBy = user;
                    currentRecord.ExistsInCurrentCulture = true;
                    currentRecord.DefaultCultureName = EditionCulture.Name;

                    foreach (var lookupControlId in lookupIds)
                    {
                        var propertyName = lookupControlId.Replace(lookupName + "_", "");
                        currentRecord[propertyName].Value = ((BaseMedianamikControl)editForm
                            .FindControl(lookupControlId)).GetValue();
                    }
                }

                DataSource = gridSource.ToArray();
                var Grid = (RadGrid)Page.FindControlR(lookupName);
                Grid.DataSource = GetRecordsForGrid();
                Grid.DataBind();
                SwitchMode(lookupName, true);
            }
        }

        public string HiddenProperties
        {
            get
            {
                return ViewState["HiddenProperties2"] == null ? string.Empty :
                    ViewState["HiddenProperties2"].ToString();
            }
            set { ViewState["HiddenProperties2"] = value; }
        }

        public bool AllowLinesReordering
        {
            get
            {
                return ViewState["AllowLinesReordering"] == null ? false :
                   (bool)ViewState["AllowLinesReordering"];
            }
            set { ViewState["AllowLinesReordering"] = value; }
        }

        public bool AllowOrderByColumn
        {
            get
            {
                return ViewState["AllowOrderByColumn"] == null ? false :
                   (bool)ViewState["AllowOrderByColumn"];
            }
            set { ViewState["AllowOrderByColumn"] = value; }
        }

        public MedianamikLookupColumn[] Columns
        {
            get
            {
                return ViewState["MedianamikLookupColumns"] == null ? new MedianamikLookupColumn[] { } :
                    ViewState["MedianamikLookupColumns"] as MedianamikLookupColumn[];
            }
            set { ViewState["MedianamikLookupColumns"] = value; }
        }

        public string AddButtonText
        {
            get
            {
                return ViewState["AddButtonText"] == null ? string.Empty :
                    ViewState["AddButtonText"].ToString();
            }
            set { ViewState["AddButtonText"] = value; }
        }

        public IEnumerable<Record> GetRecordsForGrid(string customSort, bool ascending)
        {
            IEnumerable<Record> returnedData;
            var dataSource = DataSource
                .Where(r => r.SynchronizeAction != SynchronizeActions.DeleteBranch &&
                r.SynchronizeAction != SynchronizeActions.Delete);

            if (AllowOrderByColumn && !String.IsNullOrEmpty(customSort))
            {
                if (ascending)
                {
                    returnedData = dataSource.OrderBy(r => r.Properties.First(p => String.Compare(p.NodeTypePropertyName, customSort, true) == 0
                        || p.NodeTypePropertyId.Equals(MedianamikProperties.Name)).Value.ToString());
                }
                else
                {
                    returnedData = dataSource.OrderByDescending(r => r.Properties.First(p => String.Compare(p.NodeTypePropertyName, customSort, true) == 0
                        || p.NodeTypePropertyId.Equals(MedianamikProperties.Name)).Value.ToString());
                }
            }
            else if (AllowLinesReordering)
            {
                returnedData = dataSource.OrderBy(r => r.Position);
            }
            else
            {
                returnedData = dataSource.OrderBy(r => r.Properties.First(p => p.NodeTypePropertyName.EqualsIgnoreCase(NameProperty)
                     || p.NodeTypePropertyId.Equals(MedianamikProperties.Name)).Value.ToString());
            }
            return returnedData;
        }

        public IEnumerable<Record> GetRecordsForGrid()
        {
            return GetRecordsForGrid(String.Empty, true);
        }

        void GridItemCommand(object source, GridCommandEventArgs e)
        {
            Guid nodeId;
            if (e.CommandArgument != null &&
                StringHelper.IsGuid(e.CommandArgument.ToString(), out nodeId))
            {
                var Grid = (RadGrid)source;
                var lookupName = Grid.ID;

                var records = DataSource.ToList();
                var record = records.First(r => r.Id.Equals(nodeId));
                records.Remove(record);

                if (e.CommandName.ToUpper() == "DELETE_NODE")
                {
                    //TODO : DELETE ROW
                    //Comment recuperer le noeud qu on veut detruire ?

                    record.SynchronizeAction = SynchronizeActions.Delete;
                    DataSource = records.Union(new[] { record }).ToArray();
                    Grid.DataSource = GetRecordsForGrid();
                    Grid.DataBind();
                    SwitchMode(lookupName, true);
                }
                else if (e.CommandName.ToUpper() == "EDIT_NODE")
                {
                    //Comment recuperer le noeud qu on veut editer et setter les proprietes aux controles ?
                    FillEditForm(record);
                    SwitchMode(lookupName, false);
                }
            }
        }

        private void FillEditForm(Record record)
        {
            var editForm = GetPlaceHolder(TypeName, EditFormPlaceHolderPrefix);
            var lookupIds = LookupPropertyIds[TypeName];
            var recordId = record.Id ?? Guid.NewGuid();

            foreach (var lookupControlId in lookupIds)
            {
                var propertyName = lookupControlId.Replace(TypeName + "_", "");
                if (record.HasProperty(propertyName))
                {
                    var control = ((BaseMedianamikControl)editForm.FindControl(lookupControlId));
                    control.SetValue(record[propertyName].Value);
                    control.NodeId = recordId;
                }
            }

            var saveButton = (Button)editForm.FindControl(SaveButtonPrefix + TypeName);
            saveButton.CommandArgument = recordId.ToString();
        }

        private void SetLookupViewstate(Dictionary<string, string[]> lookupPropertyIds,
            Dictionary<string, string[]> medianamikControlTypes)
        {
            LookupPropertyIds = lookupPropertyIds;
            LookupMedianamikControlTypes = medianamikControlTypes;
        }

        private void AddValidators(Control control, string validationGroup)
        {
            _valSummary = new ValidationSummary
            {
                DisplayMode = ValidationSummaryDisplayMode.BulletList,
                ShowSummary = true,
                CssClass = "ValidationSummary",
                HeaderText = Translator.Translate("Medianamik_ContentManagement",
                                                  "ValidationSummaryHeaderText"),
                ValidationGroup = validationGroup
            };

            control.Controls.Add(_valSummary);
            control.Controls.Add(new HtmlGenericControl("br"));
        }

        private void DisableClientSideValidation(Control control)
        {
            if (control is BaseValidator)
            {
                BaseValidator validator = (BaseValidator)control;
                validator.EnableClientScript = false;
            }

            foreach (Control childControl in control.Controls)
            {
                DisableClientSideValidation(childControl);
            }
        }

        public static Collection<Record> ChangeNodeOrder(List<Record> siblings,
            Guid movedNodeId, Guid? pDestinationNodeId, DropPosition pPosition)
        {
            if (siblings.Count < 2)
            {
                //Pas d'ordonancement à faire.
                return new Collection<Record>(siblings);
            }

            //Ordonner les Noeuds par position
            siblings.Sort(Record.ComparePosition);

            var movedNode = siblings.First(n => n.Id == movedNodeId);

            //Retirer le noeud de la collection
            siblings.Remove(movedNode);

            //Si destinationNodeId n'a pas de valeur, le noeud ira en première position
            var destinationNodeId = pDestinationNodeId ?? siblings[0].Id.Value;

            //Trouver le noeud situé avant
            int position = 0;

            if (siblings.Exists(n => n.Id == pDestinationNodeId))
            {
                position = siblings.FindIndex(n => n.Id == destinationNodeId) + (int)pPosition;
            }

            //Insertion du Noeud à la bonne position
            siblings.Insert(position, movedNode);

            //Mettre à jour la position
            for (short i = 0; i < siblings.Count; i++)
            {
                var currentNode = siblings[i];

                if (currentNode.Position != i)
                {
                    currentNode.Position = i;
                }
            }

            return new Collection<Record>(siblings);
        }

        void RowDrop(object sender, GridDragDropEventArgs e)
        {
            var Grid = sender as RadGrid;

            if (Grid != null && e.DraggedItems[0].OwnerGridID == Grid.ClientID &&
                String.IsNullOrEmpty(e.HtmlElement))
            {
                var records = DataSource.ToList();
                var movedNodeId = (Guid)e.DraggedItems[0].GetDataKeyValue("Id");
                var destinationNodeId = (Guid)e.DestDataItem.GetDataKeyValue("Id");
                var position = e.DropPosition == GridItemDropPosition.Above
                                ? DropPosition.Above
                                : DropPosition.Below;
                DataSource = ChangeNodeOrder(records, movedNodeId, destinationNodeId,
                                                  position).ToArray();
                Grid.DataSource = GetRecordsForGrid();
                Grid.DataBind();
            }
        }

        private void SubgridNeedDataSource(object source, GridNeedDataSourceEventArgs e)
        {
            RadGrid Grid = (RadGrid)source;
            BindSubGridDataSouce(Grid);
        }

        private void BindSubGridDataSouce(RadGrid subGrid)
        {
            if (subGrid.MasterTableView.SortExpressions.Count > 0)
            {
                subGrid.DataSource = GetRecordsForGrid(subGrid.MasterTableView.SortExpressions[0].FieldName,
                        subGrid.MasterTableView.SortExpressions[0].SortOrder == GridSortOrder.Ascending);
            }
            else
            {
                subGrid.DataSource = GetRecordsForGrid();
            }
        }

        private void subgrid_SortCommand(object source, GridSortCommandEventArgs e)
        {
            RadGrid subGrid = (RadGrid)source;
            GridSortExpression sortExpr = new GridSortExpression();
            sortExpr.FieldName = e.SortExpression;
            switch (e.OldSortOrder)
            {
                case GridSortOrder.None:
                    sortExpr.SortOrder = GridSortOrder.Ascending;
                    break;
                case GridSortOrder.Ascending:
                    sortExpr.SortOrder = GridSortOrder.Descending;
                    break;
                case GridSortOrder.Descending:
                    sortExpr.SortOrder = subGrid.MasterTableView.AllowNaturalSort ? GridSortOrder.None : GridSortOrder.Ascending;
                    break;
            }
            e.Item.OwnerTableView.SortExpressions.AddSortExpression(sortExpr);
            e.Canceled = true;
            //BindSubGridDataSouce(subGrid);
            subGrid.Rebind();
        }

        protected virtual void OnEditSubItem(object sender, CommandEventArgs e)
        {
            Guid nodeId;
            if (e.CommandArgument != null && StringHelper.IsGuid(e.CommandArgument.ToString(), out nodeId))
            {
                var Grid = ((Control)sender).FindParentControlR<RadGrid>();
                //((Control)sender).Parent.Parent.Parent.Parent.Parent.Parent.Parent.Parent;
                var lookupName = Grid.ID;

                var records = DataSource.ToList();
                var record = records.First(r => r.Id.Equals(nodeId));
                var editForm = GetPlaceHolder(lookupName, EditFormPlaceHolderPrefix);
                var saveButton = (Button)editForm.FindControl(SaveButtonPrefix + lookupName);
                saveButton.CommandArgument = nodeId.ToString();
                FillEditForm(record);
                SwitchMode(lookupName, false);
            }
        }

        protected virtual void OnDeleteSubItem(object sender, CommandEventArgs e)
        {
            Guid nodeId;
            if (e.CommandArgument != null && StringHelper.IsGuid(e.CommandArgument.ToString(), out nodeId))
            {
                var Grid = (RadGrid)((Control)sender).Parent.Parent.Parent.Parent.Parent.Parent.Parent.Parent;

                var records = DataSource.ToList();
                var record = records.First(r => r.Id.Equals(nodeId));
                records.Remove(record);

                record.SynchronizeAction = SynchronizeActions.Delete;
                DataSource = records.Union(new[] { record }).ToArray();
                Grid.DataSource = GetRecordsForGrid();
                Grid.DataBind();
            }
        }

        protected Dictionary<string, string[]> LookupMedianamikControlTypes
        {
            get
            {
                return ViewState["LookupMedianamikControlTypes"] as Dictionary<string, string[]>;
            }
            set
            {
                ViewState["LookupMedianamikControlTypes"] = value;
            }
        }

        protected Dictionary<string, string[]> LookupPropertyIds
        {
            get
            {
                return ViewState["LookupPropertyIds"] as Dictionary<string, string[]>;
            }
            set
            {
                ViewState["LookupPropertyIds"] = value;
            }
        }

        public string RadTabStripId
        {
            get
            {
                var result = ViewState["RadTabStripId"];

                if (result != null && result.ToString() != String.Empty)
                    return result.ToString();

                return null;
            }
            set { ViewState["RadTabStripId"] = value; }
        }

        public bool EnableClientScriptValidation
        {
            get
            {
                object o = ViewState["EnableClientScriptValidation"];
                if (o == null)
                {
                    return false;
                }
                return (bool)o;
            }
            set { ViewState["EnableClientScriptValidation"] = value; }
        }

        private MedianamikLookupProperties BuildLookupEditForm(bool useDataSource,
            PlaceHolder placeHolder, string lookupTypeName)
        {
            var nodeType = NodeTypeManager.GetNodeType(TypeName);

            var props = nodeType.GetAllProperties()
                .Where(p => p.MedianamikControl != null
                            && MedianamikContext.Current.MedianamikUser
                                   .CanAccessProperty(p) &&
                                   nodeType.PropertyIsVisible(p.ID) &&
                            !HiddenProperties.Split(',').Any(pr => p.Name.Equals(pr.TrimStart().TrimEnd(), StringComparison.OrdinalIgnoreCase)))
                .OrderBy(p => nodeType.GetPropertyPosition(p.ID)).ToList();

            var propertyIds = new List<string>();

            for (var i = 0; i < props.Count; i++)
            {
                var prop = props.ElementAt(i);

                if (useDataSource)
                {
                    var mkControl = prop.GetMedianamikControl(EnableClientScriptValidation,
                        EditionCulture, SubGridValidationSummary, HideNeutralLanguageIndication);
                    var control = mkControl.Control;
                    placeHolder.Controls.Add(control);
                    control.ID = lookupTypeName + "_" + prop.Name;
                    propertyIds.Add(control.ID);
                    control.DataBind();
                }
                else
                {
                    var control = new ObjectBuilder(LookupMedianamikControlTypes[lookupTypeName][i])
                        .GetInstance<IMedianamikControl>().Control;
                    control.ID = LookupPropertyIds[lookupTypeName][i]; //Important - cette ligne avant la suivante
                    placeHolder.Controls.Add(control);
                }
            }

            return new MedianamikLookupProperties(propertyIds.ToArray(), props.Select(p => p.MedianamikControl.FullName).ToArray());
        }
    }
}